<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // 需求 描述一只猫的名称，颜色，叫声，技能

    // 2. 将对象进行函数封装
    // 优点: 根据传入的参数快速生成对象
    // 缺点:
    // 1. 通过函数创建的对象和函数没有关系 (简单来说 不是构造函数本身创建的)
    // var arr = new Array();
    // console.log(arr instanceof Array);  // true

    // var obj = new Object();
    // console.log(obj instanceof Object); // true

    // 2. 公有的属性和方法重复创建(赋值给每个对象)  -> 占内存

    // function cat(name, color) {
    //     var obj = {   // new Object()
    //         name: name,
    //         color: color,
    //         species: "Cat",
    //         call: function () {
    //             console.log("喵喵");
    //         },
    //         skill: function () {
    //             console.log("捉老鼠");
    //         }
    //     }
    //     return obj;
    // }

    // var Tom = cat("Tom", "black");
    // console.log(Tom);
    // console.log(Tom instanceof cat, Tom instanceof Object); // false  true

    // var Kitty = cat("Kitty", "black");
    // console.log(Kitty);
    // console.log(Kitty instanceof cat, Kitty instanceof Object);// false  true



</script>
<script>
    // 通过对比发现 -> 想要创建对象(实例化对象) 和 函数有关系  -> 必须是构造函数创建
    // var arr = new Array();
    // console.log(arr);
    // console.log(arr instanceof Array);  // true

    // var obj = new Object();
    // console.log(obj);
    // console.log(obj instanceof Object); // true

    // 实例化   => 通过构造函数创建对象的操作叫做实例化  (new xxx())
    // 被创建的对象 => 实例化对象


    // 用户能不能自定义构造函数  ->  可以的!!

    // 如何自定义构造函数?  跟new关键词脱不开关系 (new关键词的操作)

    // String() 函数  => 1. 作为普通函数  => 函数名()  2.作为构造函数 new 函数名()
    // console.log(String(1000));  //作为函数调用 => 强制类型转换
    // console.log(new String(1000));  //作为构造函数调用 => 创建字符串(实例化对象)


    // new关键词在调用构造函数中=时做了哪些操作?
    // 1. 创建一个纯净的实例化对象 {}
    // 2. xxx
    // 3. this -> {}   将this指向创建的实例化对象  (通过this引用实例化对象的地址)
    // 4.  return this;  默认返回创建的实例化对象

    // 注意:
    // 1. 每次调用构造函数,都会重新执行构造函数中的上下文,创建新的实例化对象
    // 2. 构造函数中的this指向本次构造函数在执行过程中创建的实例化对象
    // 3. 为了区分普通函数和构造函数 建议构造函数首字母大写


    // 作为普通函数调用
    // function fn() {
    //     console.log("函数内this:", this); // this -> window
    // }

    // var result = fn();
    // console.log("返回值:", result); // undefined (函数未定义返回值 默认返回undefined)


    // 作为构造函数调用(自定义构造函数)
    /* function Fn() {
        // {}    创建一个纯净的实例化对象  
        // this -> {}   将this指向创建的实例化对象  (通过this引用实例化对象的地址)
        console.log("函数内this:", this); //  this -> {}
        console.log(this instanceof Fn);  // true

        // 用户在定义构造函数 可以将属性和方法绑定到实例化对象上


        // return this;  默认返回创建的实例化对象
    }

    // 调用构造函数Fn -> 执行构造函数中的代码 -> 创建的实例化对象赋值给变量 result(引用该内存空间)
    var result = new Fn();
    console.log("返回值:", result); // {}


    var res = new Fn();
    console.log("返回值:", res); // {} */





</script>
<script>

    // 作为构造函数调用(自定义构造函数)
    function Fn(x, y) {
        // {}    创建一个纯净的实例化对象  
        // this -> {}   将this指向创建的实例化对象  (通过this引用实例化对象的地址)
        console.log("函数内this:", this); //  this -> {}
        console.log(this instanceof Fn);  // true

        // 用户在定义构造函数中 可以将属性和方法绑定到实例化对象上
        this.x = x; // {}.a = 1
        this.y = y; // {}.b = 2;
        this.sum = function () {
            return this.a + this.b;
        }


        // return this;  默认返回创建的实例化对象
    }

    // 调用构造函数Fn -> 执行构造函数中的代码 -> 创建的实例化对象赋值给变量 result(引用该内存空间)
    var result = new Fn(1, 2);
    console.log("返回值:", result); // {}


    var res = new Fn(10, 20);
    console.log("返回值:", res); // {} 



</script>

</html>